<template>
  <div class="report-sql-preview">
    <el-alert
      v-if="!templateCode"
      type="info"
      :closable="false"
      title="请选择报表模板以生成 SQL 预览"
      class="sql-alert"
      show-icon
    />

    <section v-else class="form-section">
      <div class="section-title">
        <el-icon><Document /></el-icon>
        <span>SQL 查询语句</span>
        <div class="header-actions">
          <el-tag v-if="isStale" type="warning" class="stale-tag" size="small">
            参数已修改，建议重新预览
          </el-tag>
          <span class="updated-text" v-if="updatedAt">
            最后刷新：{{ updatedAt }}
          </span>
        </div>
      </div>

      <div class="sql-preview-toolbar">
        <el-button type="primary" :disabled="!canPreview" :loading="loading" @click="handlePreview" size="small">
          <el-icon><Refresh /></el-icon>
          刷新 SQL
        </el-button>
        <el-button :disabled="!previewSQL" @click="handleCopy" size="small">
          <el-icon><DocumentCopy /></el-icon>
          复制
        </el-button>
      </div>

      <div class="sql-preview-content">
        <el-input
          v-model="previewSQL"
          type="textarea"
          :rows="15"
          class="sql-input"
          placeholder="点击「刷新 SQL」按钮后在此处查看生成的查询语句"
          readonly
        />
      </div>

      <el-alert
        v-if="error"
        type="error"
        :closable="false"
        :title="error"
        class="sql-alert"
        show-icon
      />
    </section>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { Refresh, DocumentCopy, Document } from '@element-plus/icons-vue'
// @ts-ignore 缺少类型声明
import api from '@/utils/api'

const props = defineProps<{
  templateCode?: string | null
  params: Record<string, any> | null
}>()

const previewSQL = ref('')
const loading = ref(false)
const error = ref('')
const updatedAt = ref('')
const lastSignature = ref('')
const isStale = ref(false)

const templateCode = computed(() => props.templateCode || '')
// 使用深拷贝和排序确保参数变化能被正确检测
const paramsSignature = computed(() => {
  if (!props.params) return '{}'
  // 深拷贝对象，确保顺序一致
  const normalized = JSON.parse(JSON.stringify(props.params))
  // 对数组进行排序，确保顺序一致（特别是display_fields）
  if (normalized.display_fields && Array.isArray(normalized.display_fields)) {
    normalized.display_fields = [...normalized.display_fields].sort()
  }
  // 创建一个新的排序后的对象
  const sortedKeys = Object.keys(normalized).sort()
  const sortedObj: Record<string, any> = {}
  for (const key of sortedKeys) {
    sortedObj[key] = normalized[key]
  }
  return JSON.stringify(sortedObj)
})
const canPreview = computed(() => Boolean(templateCode.value))

const buildPreviewParams = () => {
  const payload = JSON.parse(JSON.stringify(props.params || {}))

  const candidateIds: Array<number | string> = []
  const collectId = (value?: any) => {
    if (!value) return
    if (typeof value === 'object' && 'data_source_id' in value && value.data_source_id) {
      candidateIds.push(value.data_source_id)
    }
  }

  collectId(payload.data_source_config)
  collectId(payload.source_tables)
  collectId(payload.target_table_config)
  // 遍历一级属性，找到潜在的数据源 ID
  Object.values(payload).forEach((val) => {
    collectId(val)
  })

  const dataSourceId = candidateIds.find(Boolean)
  if (dataSourceId) {
    payload.data_source_config = payload.data_source_config || {}
    payload.data_source_config.data_source_id = dataSourceId
  }

  return payload
}

const handlePreview = async () => {
  if (!canPreview.value || loading.value) return
  loading.value = true
  error.value = ''
  try {
    const payload = buildPreviewParams()
    const response = await api.post('/reports/preview-sql', {
      template_code: templateCode.value,
      params: payload
    })
    if (response.data.success) {
      previewSQL.value = response.data.data?.sql || ''
      lastSignature.value = paramsSignature.value
      isStale.value = false
      updatedAt.value = new Date().toLocaleString()
      if (!previewSQL.value) {
        error.value = '接口未返回 SQL 预览'
      }
    } else {
      error.value = response.data.message || '获取 SQL 失败'
    }
  } catch (err: any) {
    error.value = err?.response?.data?.message || err?.message || '获取 SQL 失败'
  } finally {
    loading.value = false
  }
}

const handleCopy = async () => {
  if (!previewSQL.value) return
  try {
    await navigator.clipboard.writeText(previewSQL.value)
    ElMessage.success('SQL 已复制到剪贴板')
  } catch {
    ElMessage.error('复制失败，请手动复制')
  }
}

watch(
  [() => templateCode.value, paramsSignature],
  ([newTemplateCode, newSignature], [oldTemplateCode, oldSignature]) => {
    // 如果模板代码变化，重置状态
    if (newTemplateCode !== oldTemplateCode) {
      previewSQL.value = ''
      lastSignature.value = ''
      isStale.value = false
      updatedAt.value = ''
      return
    }
    
    // 如果已经有预览SQL，检查参数是否变化
    if (previewSQL.value) {
      isStale.value = newSignature !== lastSignature.value
    }
  },
  { immediate: false, deep: false }
)
</script>

<style scoped>
.report-sql-preview {
  width: 100%;
}

.form-section {
  margin-bottom: 24px;
  padding: 24px;
  border: 1px solid #e4e7ed;
  border-radius: 12px;
  background: linear-gradient(135deg, #ffffff 0%, #fafbfc 100%);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
  transition: all 0.3s ease;
}

.form-section:hover {
  border-color: #c0c4cc;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
  transform: translateY(-1px);
}

.section-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  font-weight: 600;
  margin-bottom: 20px;
  color: #1f2937;
  font-size: 16px;
  padding-bottom: 12px;
  border-bottom: 2px solid #f0f0f0;
  position: relative;
}

.section-title::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 60px;
  height: 2px;
  background: linear-gradient(90deg, #409eff, #67c23a);
  border-radius: 1px;
}

.section-title .el-icon {
  font-size: 18px;
  color: #409eff;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-left: auto;
}

.updated-text {
  font-size: 12px;
  color: #909399;
}

.sql-preview-toolbar {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
}

.sql-preview-content {
  background: white;
  border-radius: 8px;
  border: 1px solid #d1d5db;
  padding: 12px;
  transition: all 0.3s ease;
}

.sql-preview-content:hover {
  border-color: #c0c4cc;
}

.sql-input :deep(textarea) {
  font-family: 'Fira Code', 'Consolas', 'SFMono-Regular', monospace;
  font-size: 13px;
  background: #f5f5f5;
  border: none;
  resize: none;
}

.sql-input :deep(.el-textarea__inner) {
  background: #f5f5f5;
  border: none;
  box-shadow: none;
  border-radius: 4px;
}

.sql-alert {
  margin-top: 16px;
}

.stale-tag {
  font-size: 12px;
}
</style>


